/**
 * 所有版权归 广西梧州 陈锦韬 所有
 *
 * @Title: ContainerMemmory
 * @Package com.rx.core.mode
 * @Description: 容器内存
 * @author: 陈锦韬
 * @date: 2021\6\15 0015
 * @version V1.0
 * @Copyright: 2021 陈锦韬  All rights reserved.
 */
package com.rx.core.mode;

import com.rx.core.handler.RxHandler;
import com.rx.core.handler.RxHandlerAfter;
import com.rx.core.handler.RxHandlerPrev;
import com.rx.core.handler.RxHandlerWraper;
import com.rx.core.util.RxSpecialUtil;
import com.rx.core.util.RxUtil;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author: Administrator
 * @Description: 容器内存
 * @date: 2021\6\15 0015
 */
public class ContainerMemmory {
    /**
     * 处理器容器
     */
    public Map<String, List<RxHandlerWraper>> container = new HashMap<>();
    public Map<String, List<RxHandlerWraper>> containerPrev = new HashMap<>();
    public Map<String, List<RxHandlerWraper>> containerAfter = new HashMap<>();
    private volatile boolean casLock = false;
    private ReentrantLock lock = new ReentrantLock();

    protected List<RxHandlerWraper> mergeList(Map<String, List<RxHandlerWraper>> container,String key){
        List<RxHandlerWraper>  result = new ArrayList<>();
        for (Map.Entry<String, List<RxHandlerWraper>> stringListEntry : container.entrySet()) {
            if (stringListEntry.getKey().equalsIgnoreCase(key)){
                result.addAll(stringListEntry.getValue());
            }
            if (stringListEntry.getKey().equalsIgnoreCase(HandlerContainer.ALL_PREFIX)){
                result.addAll(stringListEntry.getValue());
            }
            if (stringListEntry.getKey().equalsIgnoreCase(HandlerContainer.EXT_PREFIX + key)){
                continue;
            }
            if (stringListEntry.getKey().startsWith(HandlerContainer.EXT_PREFIX)){
                result.addAll(stringListEntry.getValue());
            }
        }
        return result;
    }
    public List<RxHandlerWraper> mergeList(Class cls,String key){
        return (List<RxHandlerWraper>)RxSpecialUtil.getByLock(casLock,lock,()->{
            return mergeList(HandlerContainer.containerByClass(cls,container,containerPrev,containerAfter),key);
        });
    }
    protected List<RxHandlerWraper> mergeResult(String key,Class cls,Map<String, List<RxHandlerWraper>> container) {
        List<RxHandlerWraper> reuslt = new ArrayList<>();
        // ALL
        RxUtil.ListUtil.merge(reuslt, AllRequestHandlerContainer.getAllList(this,cls, key));
        // 其他模式
        RxUtil.ListUtil.merge(reuslt, mergeList(container, key));
        // 优先级排序
        return reuslt.stream().distinct().sorted(Comparator.comparingInt(e -> e.order(key))).collect(Collectors.toList());
    }
    public List<RxHandlerWraper> getHandler(String key){
        return mergeResult(key, RxHandler.class,HandlerContainer.containerByClass(RxHandler.class,container,containerPrev,containerAfter));
    }
    public List<RxHandlerWraper> getPrevHandler(String key){
        return mergeResult(key, RxHandlerPrev.class,HandlerContainer.containerByClass(RxHandlerPrev.class,container,containerPrev,containerAfter));
    }
    public List<RxHandlerWraper> getAfterHandler(String key){
        return mergeResult(key, RxHandlerAfter.class,HandlerContainer.containerByClass(RxHandlerAfter.class,container,containerPrev,containerAfter));
    }
    private HandlerContainer.HandlerAllList getHandlerListWithoutLock(String key){
        HandlerContainer.HandlerAllList handlerAllList = new HandlerContainer.HandlerAllList();
        handlerAllList.setPrevList(getPrevHandler(key));
        handlerAllList.setOverList(getHandler(key));
        handlerAllList.setAfterList(getAfterHandler(key));
        return handlerAllList;
    }
    public HandlerContainer.HandlerAllList getHandlerList(String key){
        return (HandlerContainer.HandlerAllList) RxSpecialUtil.getByLock(casLock,lock,()->getHandlerListWithoutLock(key));
    }
    /**
     * 有反射，不要轻易删除
     * @param key
     * @param cls
     * @param handlerWraper
     */
    public void setHandler(String key, Class cls, RxHandlerWraper handlerWraper){
        RxSpecialUtil.setByLock(lock,e->casLock = (boolean)e,()->{
            List<RxHandlerWraper> list = HandlerContainer.containerNotNull(key,
                    HandlerContainer.containerByClass(cls,container,containerPrev,containerAfter));
            list.add(handlerWraper);
        });
    }
    public void remove(String key, Class cls,RxHandlerWraper handlerWraper){
        RxSpecialUtil.setByLock(lock,e->casLock = (boolean)e,()->{
            List<RxHandlerWraper> list = HandlerContainer.containerNotNull(key,
                    HandlerContainer.containerByClass(cls,container,containerPrev,containerAfter));
            list.remove(handlerWraper);
        });
    }
}
